//Clase genérica que define la acción de los BOT cuando llega su turno.
//Todas las clases que heredan de ésta deben implementar el método chooseCardToPlay().
//Es común a todos los BOT, independientemente de su estrategia, que si se ha jugado una carta
//taketwo o takefour, el priorizar jugar una similar.
//En el caso de que jueguen una carta cambio de color, cambiarán al color mayoritario en sus manos.
package UnoBots;

import Cards.UnoCard;
import Game.PlayerUNO;
import Game.UnoGame;

public abstract class BotPlayerUNO extends PlayerUNO{
    
    public BotPlayerUNO(String s){
        super(s);
        currentGame = null;
    }
    
    /**
    * This method makes turn of player
    * @param currentGame 
    */
    
    @Override
    public void myTurn(UnoGame currentGame){
        System.out.println("The hand of this bot is: " + hand);
        UnoCard uc = new UnoCard(UnoCard.Number.ZERO, UnoCard.Colour.RED);
        this.currentGame = currentGame;
        boolean played = false;
        System.out.println("Juega: " + this.toString());
        if (currentGame.getTopCard().getRank().equals(UnoCard.Number.TAKETWO) && !currentGame.getRobado()){
            for (UnoCard c : hand){
                if (c.getRank().equals(UnoCard.Number.TAKETWO)){
                    //playCard(c);
                    uc = c;
                    played = true;
                }
            }
            if (played){
                playCard(uc);
            }
            if (!played){
                for (int i = 0; i<currentGame.getCardsToTake(); i++){
                    hand.add(currentGame.getFirstOnDeck());
                }
                currentGame.setRobado(true);
                System.out.println(this.toString() + " Roba "+currentGame.getCardsToTake() +  "cartas.");
                currentGame.setCardsToTake(0);
            }
        }
        else if (currentGame.getTopCard().getRank().equals(UnoCard.Number.TAKEFOUR) && !currentGame.getRobado()){
            for (UnoCard c : hand){
                if (c.getRank().equals(UnoCard.Number.TAKEFOUR)){
                    //playCard(c);
                    uc = c;
                    played = true;
                }
            }
            if (played){
                playCard(uc);
            }
            if (!played){
                for (int i = 0; i<currentGame.getCardsToTake(); i++){
                    hand.add(currentGame.getFirstOnDeck());
                }
                currentGame.setRobado(true);
                System.out.println(this.toString() + " Roba "+currentGame.getCardsToTake() +  "cartas.");
                currentGame.setCardsToTake(0);
            }
        }
        else{
            boolean found = false;
            for (UnoCard c : hand){
                if (canPlay(c)){
                    found = true;
                }
            }
            //Si podemos jugar al menos una carta, elegimos cual jugamos.
            if (found){
                chooseCardToPlay();
            }
            //En caso contrario, robamos una (o dos) cartas.
            else{
                System.out.println("BOT ROBA CARTA");
                drawCard();
            }
            currentGame.setRobado(false);
        }
    }
    
     /**
     * This method makes a change of colour
     * @return UnoCard to change to the most common colour in the hand
     */
    
    //Buscamos el color mayoritario en la mano del bot y ese es el que elejimos
    @Override
    public UnoCard.Colour changeColour(){
        int [] colours = new int[4];
        int mayor = 0;
        int colour = 0;
        colours[0] = 0;
        colours[1] = 0;
        colours[2] = 0;
        colours[3] = 0;
        for (UnoCard c : hand){
            if (c.getSuit().equals(UnoCard.Colour.RED)){
                colours[0]++;
            }
            if (c.getSuit().equals(UnoCard.Colour.BLUE)){
                colours[1]++;
            }
            if (c.getSuit().equals(UnoCard.Colour.YELLOW)){
                colours[2]++;
            }
            if (c.getSuit().equals(UnoCard.Colour.GREEN)){
                colours[3]++;
            }
        }
        for (int i = 0; i<colours.length; i++){
            if (colours[i] > mayor){
                mayor = colours[i];
                colour = i;
            }
        }
        switch (colour){
            case 0:
                return UnoCard.Colour.RED;
            case 1:
                return UnoCard.Colour.BLUE;
            case 2:
                return UnoCard.Colour.YELLOW;
            case 3:
                return UnoCard.Colour.GREEN;
            default:
                //No debe llegar aqui
                return UnoCard.Colour.NEUTRAL;
        }
    }
    
    /**
    * This method choose the BotPlayerUNO
    * @param s
    * @return the BotPlayer to use
    */
    
    public static BotPlayerUNO getInstance(String s, int i){
        int n = i%3;
        switch (n){
            case 0:
                return new BotColours(s);
            case 1:
                return new BotKeepSpecials(s);
            case 2: 
                return new BotNumbers(s);
            case 3:
                return new BotSpecials(s);
            default:
                return null;
        }
    }
}